home *** CD-ROM | disk | FTP | other *** search
/ Collection of Tools & Utilities / Collection of Tools and Utilities.iso / pascal / tppop16.zip / DICE.PAS next >
Pascal/Delphi Source File  |  1988-09-29  |  9KB  |  369 lines

  1. {$R-,S-,I+,D+,T+,F-,V-,B-,N-,L+ }
  2. Unit Dice;
  3.  
  4. Interface
  5.  
  6. Uses Crt,
  7.      Windows,
  8.      popup;     { only required for the replacedment READKEY function }
  9.  
  10. Procedure PopDice;  { units listed in the INTERFACE are FAR }
  11.  
  12. Implementation
  13.  
  14. Type
  15.   String20 = String[20];
  16.  
  17. Var
  18.   Number  : Integer;
  19.   Adds    : Integer;
  20.   Done    : Boolean;
  21.   OldLine : String20;
  22.   OldNumber: Integer;
  23.   OldSides : Integer;
  24.   OldAdds  : Integer;
  25.   Sides   : Integer;
  26.   OldRoll : Integer;
  27.   WinX    : Integer;
  28.   WinY    : Integer;
  29.   Line    : String20;
  30.   Dee : Boolean;
  31.   Adder : Boolean;
  32.  
  33. Const
  34.     ESC = #27;
  35.     CR = #13;
  36.     BS = #8;
  37.     F1 = #59;
  38.     F2 = #60;
  39.     F3 = #61;
  40.     F4 = #62;
  41.     F5 = #63;
  42.     F6 = #64;
  43.     F7 = #65;
  44.     F8 = #66;
  45.     F9 = #67;
  46.     F10 = #68;
  47.     Ctrl_End = #117;
  48.     UpAr = #72;
  49.     DnAr = #80;
  50.     LfAr = #75;
  51.     RtAr = #77;
  52.  
  53. Function IStr(Number : Integer) : String20;
  54.  
  55. { converts an integer to a string and returns it }
  56. { as a function result, which is more convient.  }
  57.  
  58. Var
  59.   Temp : String20;
  60.  
  61. Begin
  62.   Str(Number,Temp);
  63.   IStr := Temp;
  64. End;
  65.  
  66. Procedure BreakUp(Line : String20;Var Number,Sides,Adds : Integer);
  67.  
  68. { splits the string containing the dice roll into three numbers:    }
  69. {  number of dice, how many sides, and modifier, i.e. 2d6+1 returns }
  70. {  2 dice of six sides with a modifer of 1.                         }
  71.  
  72. Var
  73.   Result : Integer;
  74.   TempLine : String20;
  75.   PlusMinus : Integer;
  76.   Index : Integer;
  77.  
  78. Begin
  79.   Index := Pos('d',Line);
  80.   If Index = 0 Then Index := Succ(Length(Line));
  81.   Val(Copy(Line,1,Pred(Index)),Number,Result);  { get number of sides }
  82.   Delete(Line,1,Index);                         { and remove from string }
  83.   If Line = ''            { if only dice count is given then use old }
  84.     Then Begin            { number of sides and old modifier         }
  85.       Sides := OldSides;
  86.       Adds  := OldAdds;
  87.     End
  88.   Else Begin
  89.     PlusMinus := Pos('+',Line);                        { look for modifier    }
  90.     If PlusMinus = 0 Then PlusMinus := Pos('-',Line);  { it could be negative }
  91.     If PlusMinus = 0
  92.       Then Begin
  93.         TempLine := Line;
  94.         Line := '';
  95.       End
  96.     Else Begin
  97.       TempLine := Copy(Line,1,Pred(PlusMinus));   { get number of sides    }
  98.       Delete(Line,1,Pred(PlusMinus));             { and remove from string }
  99.     End;
  100.     If TempLine = ''
  101.       Then Sides := OldSides
  102.     Else Val(TempLine,Sides,Result);             { sides now as integer }
  103.     If Sides = 0 Then Sides := OldSides;         { use old if zero }
  104.     If Line[1] = '+' Then Delete(Line,1,1);
  105.     Adds := 0;
  106.     If Line <> '' Then
  107.     Begin
  108.       Val(Line,Adds,Result);                     { get modifier }
  109.       If Result <> 0 Then Val(Copy(Line,1,Pred(Result)),Adds,Result);
  110.     End;
  111.   End;
  112.   OldNumber := Number;                   { make old values equal new values }
  113.   OldSides  := Sides;
  114.   OldAdds   := Adds;
  115. End;
  116.  
  117. Procedure Show(Line : String20);
  118.  
  119. { given a string with a dice roll, breaks it up and displays it }
  120.  
  121. Begin
  122.   GotoXY(2,2);
  123.   ClrEol;
  124.   BreakUp(Line,Number,Sides,Adds);
  125.   Write(Number,'d',Sides);
  126.   If Adds > 0 Then Write('+');
  127.   If Adds <> 0 Then Write(Adds);
  128.   Write(' = ');
  129. End;
  130.  
  131. Procedure ShowOld;
  132.  
  133. { displays the old dice roll }
  134.  
  135. Begin
  136.   If OldRoll <> 0 Then
  137.   Begin
  138.     Show(OldLine);
  139.     Write(OldRoll);
  140.   End;
  141. End;
  142.  
  143. Function Roll(Number,Sides,Adds : Integer) : Integer;
  144.  
  145. { rolls the dice and adds the modifier }
  146.  
  147. Var
  148.   Counter : Integer;
  149.  
  150. Begin
  151.   For Counter := 1 to Number do Adds := Succ(Adds+Random(Sides));
  152.   Roll := Adds;
  153. End;
  154.  
  155. Procedure MkLine(Var Line : String20;Sides : Integer);
  156.  
  157. { fixes the dice roll string in case of any oddities }
  158.  
  159. Var
  160.  Position : Integer;
  161.  
  162. Begin
  163.   If Line = ''                            { if no count the use 1d }
  164.     Then Line := Concat('1d',IStr(Sides))
  165.   Else Begin
  166.     Position := Pos('d',Line);
  167.     If Position <> 0
  168.       Then Line := Copy(Line,1,Pred(Position))
  169.     Else Begin
  170.       Position := Pos('+',Line);
  171.       If Position = 0 Then Position := Pos('-',Line);
  172.       If Position <> 0 Then Line := Copy(Line,1,Pred(Position));
  173.     End;
  174.     Line := Line + 'd';
  175.     Line := Concat(Line,IStr(Sides));
  176.   End;
  177. End;
  178.  
  179. Procedure FunctionKey(Var KeyCode : Char);
  180.  
  181. { processes the function keys, F01 - F10 }
  182.  
  183. Var
  184.   K : Char;
  185.  
  186. Begin
  187.   K := popup.ReadKey;
  188.   KeyCode := CR;
  189.   Case K of
  190.     F1  : MkLine(Line,100);
  191.     F2  : MkLine(Line,20);
  192.     F3  : MkLine(Line,12);
  193.     F4  : MkLine(Line,4);
  194.     F6  : MkLine(Line,6);
  195.     F8  : MkLine(Line,8);
  196.     F10 : MkLine(Line,10);
  197.     Else KeyCode := #0;
  198.   End;
  199. End;
  200.  
  201. Procedure NumberKey(Var Line : String20;Var KeyCode : Char);
  202.  
  203. { processes a numeric keystroke }
  204.  
  205. Begin
  206.   If Length(Line) < 13           { 13 digits is the absolute limit }
  207.     Then Line := Line + KeyCode
  208.   Else KeyCode := #0;            { trash the key if string is full }
  209. End;
  210.  
  211. Procedure AdderKey(Var Line : String20;Var KeyCode : Char);
  212.  
  213. { process the + or - key for any dice modifiers }
  214.  
  215. Var
  216.   Position : Integer;
  217.  
  218. Begin
  219.   If (Not Adder)
  220.     Then Begin
  221.       If Line = ''              { if blank string the use old number and sides }
  222.         Then Begin
  223.           Str(OldNumber,Line);
  224.           Line := Line + 'd';
  225.           Line := Concat(Line,IStr(OldSides));
  226.           Write(Line);
  227.         End
  228.       Else If Not Dee Then      { if the 'd' character hasn't been pressed }
  229.       Begin
  230.         Line := Line + 'd';
  231.         Dee := True;
  232.         Write('d');
  233.       End;
  234.       If Pos('d',Line) = Length(Line) Then  { if no sides the use old sides }
  235.       Begin
  236.         Line := Concat(Line,IStr(OldSides));
  237.         Write(OldSides);
  238.       End;
  239.       Adder := True;
  240.       Line := Line + KeyCode;
  241.     end
  242.   Else KeyCode := #0;
  243. End;
  244.  
  245. Procedure DeeKey(Var Line : String20;Var KeyCode : Char);
  246.  
  247. { fix the roll string when the 'd' key is pressed }
  248.  
  249. Begin
  250.   If Not Dee
  251.     Then Begin
  252.       Dee := True;
  253.       If Line = '' Then         { if no dice count then use 1 }
  254.       Begin
  255.         Line := '1';
  256.         Write('1');
  257.       End;
  258.       Line := Line + 'd';
  259.       KeyCode := 'd';
  260.     End
  261.   Else KeyCode := #0;
  262. End;
  263.  
  264. Procedure BackSpace(Var Line : String20;Var KeyCode : Char);
  265.  
  266. { process destructive backspace }
  267.  
  268. Begin
  269.   If Line <> ''  { do nothing if blank line }
  270.     Then Begin
  271.       If Line[Length(Line)] = 'd' Then Dee := False;  { remove 'd' }
  272.       If Line[Length(Line)] In['-','+'] Then Adder := False;  { remove + or - }
  273.       Delete(Line,Length(Line),1);   { remove last character }
  274.       Write(BS,' ');               { backspace and space - backup again later }
  275.     End
  276.   Else KeyCode := #0;
  277. End;
  278.  
  279. Procedure CarriageExit(Var Line : String20);
  280.  
  281. { Carriage Return processing }
  282.  
  283. Begin
  284.   If Line = '' Then            { if blank line then use old dice roll }
  285.   Begin
  286.     Str(OldNumber,Line);
  287.     Line := Line + 'd';
  288.     Line := Concat(Line,IStr(OldSides));
  289.     If OldAdds <> 0 Then
  290.     Begin
  291.       If OldAdds > 0 Then Line := Line + '+';
  292.       Line := Concat(Line,IStr(OldAdds));
  293.     End;
  294.   End;
  295. End;
  296.  
  297. Procedure GetLine(Var Line : String20);
  298.  
  299. { accepts a dice roll from the keyboard, will not allow illegal keystrokes }
  300. Var
  301.   KeyCode : Char;
  302.  
  303. Begin
  304.   Dee := False;
  305.   Adder := False;
  306.   Repeat
  307.     KeyCode := popup.ReadKey;
  308.     Case KeyCode of
  309.       #0       : FunctionKey(KeyCode);
  310.       Esc      : Done := True;             { exit the popup program }
  311.       '0'..'9' : NumberKey(Line,KeyCode);  { digit key }
  312.       #43,
  313.       #45      : AdderKey(Line,KeyCode);   { + or - }
  314.       #32,
  315.       #68,
  316.       #100     : DeeKey(Line,KeyCode);     { 'd', 'D' or space }
  317.       BS       : BackSpace(Line,KeyCode);  { backspace }
  318.       CR       : CarriageExit(Line);       { carriage return }
  319.       Else KeyCode := #0;                  { trash illegal keys }
  320.     End;
  321.  
  322.     If (KeyCode <> CR) And (KeyCode <> #0) Then Write(KeyCode);
  323.   Until Done or (KeyCode = CR);
  324. End;
  325.  
  326. Procedure PopDice;
  327.  
  328. { saves the underlying screen, displays the menu, and accepts entry }
  329.  
  330. Begin
  331.   Done :=